<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <script type="text/javascript" src='../javascript/SurfacePlot.js'>
        </script>
        <script type="text/javascript" src='../javascript/ColourGradient.js'>
        </script>
        <script type="text/javascript" src="../javascript/glMatrix-0.9.5.min.js">
        </script>
        <script type="text/javascript" src="../javascript/webgl-utils.js">
        </script>
		<script type="text/javascript" src="../javascript/underscore-1.3.1.min.js">
        </script>
        <title>SurfacePlot animation example</title>
		
		<!-- The following are the WebGL shaders. -->
		
        <script id="shader-fs" type="x-shader/x-fragment">
            #ifdef GL_ES
            precision highp float;
            #endif
            varying vec4 vColor;
            varying vec3 vLightWeighting;
            void main(void)
            {
            gl_FragColor = vec4(vColor.rgb * vLightWeighting, vColor.a);
            }
        </script>
		
        <script id="shader-vs" type="x-shader/x-vertex">
            attribute vec3 aVertexPosition;
            attribute vec3 aVertexNormal;
            attribute vec4 aVertexColor;
            uniform mat4 uMVMatrix;
            uniform mat4 uPMatrix;
            uniform mat3 uNMatrix;
            varying vec4 vColor;
            uniform vec3 uAmbientColor;
            uniform vec3 uLightingDirection;
            uniform vec3 uDirectionalColor;
            varying vec3 vLightWeighting;
            void main(void)
            { 
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); 
            vec3 transformedNormal = uNMatrix * aVertexNormal;  
            float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0); 
            vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting; 
            vColor = aVertexColor;
            }
        </script>
		
        <script id="axes-shader-fs" type="x-shader/x-fragment">
            precision mediump float;
            varying vec4 vColor;
            void main(void)
            {
            gl_FragColor = vColor;
            }
        </script>
		
        <script id="axes-shader-vs" type="x-shader/x-vertex">
            attribute vec3 aVertexPosition;
            attribute vec4 aVertexColor;
            uniform mat4 uMVMatrix;
            uniform mat4 uPMatrix;
            varying vec4 vColor;
            uniform vec3 uAxesColour;
            void main(void) 
            { 
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);  
            vColor =  vec4(uAxesColour, 1.0); 
            } 
        </script>
		
        <script id="texture-shader-fs" type="x-shader/x-fragment">
            #ifdef GL_ES
            precision highp float;
            #endif
            varying vec2 vTextureCoord;
            uniform sampler2D uSampler;
            void main(void)
            {
            gl_FragColor = texture2D(uSampler, vTextureCoord);
            }
        </script>
		
        <script id="texture-shader-vs" type="x-shader/x-vertex">
            attribute vec3 aVertexPosition;
            attribute vec2 aTextureCoord;
            varying vec2 vTextureCoord;
            uniform mat4 uMVMatrix;
            uniform mat4 uPMatrix; 
            void main(void) 
            {  
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); 
            vTextureCoord = aTextureCoord; 
            }
        </script>
		
    </head>
    <body style="background:#000">
        <div>
            <br>
            <br>
            <br>
            <span style="color: #ffffff">(1) Set frames per second: </span><input type="text" id="fps" value=10> <span style="color: #ffffff">Refresh the browser before setting this. </span>
            <br>
            <br>
            <br>
			<span style="color: #ffffff">(2) Open a CSV file: </span>
            <input type="file" id="filePicker" name="files[]" />
			<br>
            <br>
            <br>
            <span style="color: #ffffff">(3) Drag to rotate. Press the shift key and drag the mouse to scale the surface plot.</span>
            <br>
            <br>
        </div>
        <div>
            <div id='surfacePlotDiv' style="float: left; width: 450px; height: 450px;">
                <!-- SurfacePlot goes here... -->
            </div>
            <div id='surfacePlotDiv2' style="float: left; width: 450px; height: 450px;">
                <!-- another SurfacePlot goes here... -->
            </div>
        </div>
        <script type='text/javascript'>
        	
			// Check for the various File API support.
            if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
                alert('The File APIs are not fully supported by your browser.');
            }
            
            function handleFileSelect(evt){
                var files = evt.target.files;
                var f = files[0];
                
                // Only process CSV files.
                if (!f.type.match('text/csv')) {
                    alert("Please specify a valid CSV file.");
                    return;
                }
                
                var reader = new FileReader();
                
                // Closure to capture the file information.
                reader.onload = (function(theFile){
                    return function(e){
                    
                        var csvData = e.target.result;
                        var frames = formatDataForChart(csvData);
						renderChart(frames);
                    };
                })(f);
                
                reader.readAsText(f);
            }
            
            document.getElementById('filePicker').addEventListener('change', handleFileSelect, false);
            
            var surfacePlot;
            
			/*
			 * Take the text from the file and place it in a 4-d array.
			 * The first dimension is time, represented as a frame.
			 * The subsequent dimensions are the XY-indices and the Z-values.
			 * 
			 * The Z-values are normaalized to the [0, 1] interval.
			 * 
			 * IMPORTANT - I'm assuming that each fram has exactly the same number of
			 * X- and Y-values. Since the surface plot is based upon Z-values projected
			 * above an XY grid, we don't actually care about the actual XY magnitudes.
			 * They're just labels.
			 */
            function formatDataForChart(allText){
                var allTextLines = allText.split(/\r\n|\n/);
                var headers = allTextLines[0].split(',');
				var line;
				var xValues = [];
				var yValues = [];
				var zValues = [];
				var frameIds = [];
				var maxZValue = Number.MIN_VALUE;
				var minZValue = Number.MAX_VALUE;
                
                for (var i = 1; i < allTextLines.length; i++) {
					line = allTextLines[i];
                    var data = line.split(',');
					
                    if (data.length == headers.length) {
                    
                        xValues.push(data[0]);
                        yValues.push(data[1]);
                        zValues.push(data[2]);
                        frameIds.push(data[3]);
						
						if (data[2] > maxZValue)
						  maxZValue = data[2];
						  
						if (data[2] < minZValue)
                          minZValue = data[2];
                    }
                }
				
				frameIds = _.uniq(frameIds);
			    xValues = _.uniq(xValues);
			    yValues = _.uniq(yValues);
				
				var frames = [];
                var rows = [];
                var cols = [];
				var idx = 0;
				var normalizedVal;
				
				_.forEach(frameIds, function(frameId){
					rows = [];
					_.forEach(xValues, function(x){
						cols = [];
						_.forEach(yValues, function(y){
							normalizedVal = (zValues[idx] - minZValue) / (maxZValue - minZValue);
							cols.push(normalizedVal);
							idx++;
						});
						rows.push(cols);
					});
					frames.push(rows);
				});
				
				return {
					xLabels: xValues,
					yLabels: yValues,
					headers: headers,
					frames: frames
				};
            }
            
            function renderChart(dataAndLabels){
				
                var numRows = dataAndLabels.frames[0].length;
                var numCols = dataAndLabels.frames[0][0].length;
                
                var tooltipStrings = new Array();
                var values = new Array();
                var data = {
                    nRows: numRows,
                    nCols: numCols,
                    formattedValues: dataAndLabels.frames,
					frames: true
                };
				
                surfacePlot = new SurfacePlot(document.getElementById("surfacePlotDiv"));
                
                var fillPly = true;
                
                // Define a colour gradient.
                var colour1 = {
                    red: 0,
                    green: 0,
                    blue: 255
                };
                var colour2 = {
                    red: 0,
                    green: 255,
                    blue: 255
                };
                var colour3 = {
                    red: 0,
                    green: 255,
                    blue: 0
                };
                var colour4 = {
                    red: 255,
                    green: 255,
                    blue: 0
                };
                var colour5 = {
                    red: 255,
                    green: 0,
                    blue: 0
                };
                var colours = [colour1, colour2, colour3, colour4, colour5];
                
                // Axis labels.
                var xAxisHeader = dataAndLabels.headers[0];
                var yAxisHeader = dataAndLabels.headers[1];
                var zAxisHeader = dataAndLabels.headers[2];
                
                var renderDataPoints = false;
                var background = '#ffffff';
                var axisForeColour = '#000000';
                var hideFloorPolygons = true;
                var chartOrigin = {
                    x: 150,
                    y: 150
                };
                
                // Options for the basic canvas plot.
                var basicPlotOptions = {
                    fillPolygons: fillPly,
                    tooltips: tooltipStrings,
                    renderPoints: renderDataPoints
                }
                
                // Options for the webGL plot.
                var xLabels = dataAndLabels.xLabels;
                var yLabels = dataAndLabels.yLabels;
                var zLabels = [0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5]; // These labels are used when autoCalcZScale is false;
                var fps = document.getElementById("fps").value;
                var glOptions = {
                    xLabels: xLabels,
                    yLabels: yLabels,
                    zLabels: zLabels,
                    autoCalcZScale: false, // This should be set to false since we've normalized our data to [0, 1];
                    framesPerSecond: fps
                };
                
                // Options common to both types of plot.
                var options = {
                    xPos: 0,
                    yPos: 0,
                    width: 400,
                    height: 400,
                    colourGradient: colours,
                    xTitle: xAxisHeader,
                    yTitle: yAxisHeader,
                    zTitle: zAxisHeader,
                    backColour: background,
                    axisTextColour: axisForeColour,
                    hideFlatMinPolygons: hideFloorPolygons,
                    origin: chartOrigin
                };
                
                surfacePlot.draw(data, options, basicPlotOptions, glOptions);
                
                // Link the two charts for rotation.
                var plot1 = surfacePlot.getChart();
            }
            
        </script>
    </body>
</html>
